import { SearchControl } from '@/components/Table/hooks/useSearch';
import { PageControl } from '@/components/Table/hooks/usePagination';
import { Options } from '@/components/Table/types';
import { DataResponse, PageInfo, QueryCondition } from '@/services/core';
import { ObjectUtil } from '@/utils/ObjectUtil';
import { RowEnabled, RowStatus, TableControl } from '@/components/Table/hooks/useTable';
import { HttpUtil } from '@/utils/HttpUtil';
import { AssociationService, DataService } from '@/services/core/DataService';
import { DateUtil } from '@/utils/DateUtil';
import { TableModel } from '@/components/Table/ManageTable/model';

export const getQueryCondition = <T>(
  searchControl: SearchControl<T>,
  pageControl: PageControl,
  tableControl: TableControl<T>,
  options: Options<T>
): QueryCondition<T> => {
  const queryCondition: QueryCondition<T> = {
    query: {},
    pageCondition: {
      pageNum: pageControl.current,
      pageSize: pageControl.pageSize,
    },
    orderConditions:
      tableControl.prop !== null && tableControl.order !== null
        ? [
            {
              columns: [tableControl.prop],
              mode: tableControl.order,
            },
          ]
        : [],
    columnCondition: {
      timeConditions: [],
      numberConditions: [],
      categoryConditions: [],
    },
  };
  ObjectUtil.keys(searchControl.query).forEach(key => {
    const option = options[key];
    if (option?.type === 'time') {
      (queryCondition.query as Partial<T>)[key] = undefined;
      const tuple = searchControl.query[key] as [Date | null, Date | null];
      if (tuple[0] !== null && tuple[1] !== null) {
        queryCondition.columnCondition?.timeConditions?.push({
          column: key,
          begin: DateUtil.format(tuple[0]),
          end: DateUtil.format(tuple[1]),
        });
      }
    } else {
      queryCondition.query[key as keyof T] = searchControl.query[key] as T[keyof T];
    }
  });
  return queryCondition;
};

export type Select<T> = () => Promise<DataResponse<PageInfo<T>>>;

export const selectLikeWithStatus = async <T>(
  selectLike: (condition: QueryCondition<T>) => Promise<DataResponse<PageInfo<T>>>,
  condition: QueryCondition<T>,
  pageControl: PageControl,
  tableControl: TableControl<T>
): Promise<DataResponse<PageInfo<T>>> => {
  tableControl.loading = true;
  try {
    const resp = await selectLike(condition);
    tableControl.tableData = HttpUtil.getList(resp).map(v => {
      (v as T & RowStatus).rowStatus = 0;
      return v as T & RowStatus;
    });
    pageControl.total = HttpUtil.getPageInfo(resp).total;
    pageControl.pages = HttpUtil.getPageInfo(resp).pages;
    return resp;
  } finally {
    tableControl.loading = false;
  }
};

export const selectLikeWithEnabled = async <T extends TableModel, N extends TableModel>(
  associationService: AssociationService<T, unknown, N, unknown, unknown, unknown>,
  modelService: DataService<N, unknown>,
  id: unknown | undefined,
  condition: QueryCondition<N>,
  pageControl: PageControl,
  tableControl: TableControl<N>
): Promise<DataResponse<PageInfo<N>>> => {
  tableControl.loading = true;
  try {
    const associationList = HttpUtil.getList(
      await associationService.select({
        query: associationService.model(id),
      })
    );
    // console.log(associationList);
    const nIds = HttpUtil.getData(
      await modelService.selectByIds(associationList.map(v => associationService.getNid(v)))
    ).map(v => v.id);
    // console.log(nIds);

    const resp = await modelService.selectLike(condition);
    tableControl.tableData = HttpUtil.getList(resp).map(v => {
      (v as N & RowEnabled).enabled = nIds.includes(v.id);
      const association = associationList.find(association => associationService.getNid(association) === v.id);
      if (association) {
        v.readOnly = association.readOnly;
      } else {
        v.readOnly = false;
      }
      return v as N & RowEnabled;
    });
    pageControl.total = HttpUtil.getPageInfo(resp).total;
    pageControl.pages = HttpUtil.getPageInfo(resp).pages;
    return resp;
  } finally {
    tableControl.loading = false;
  }
};
